﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CmdStructureWallHole.h"
#include "StructureCmdIds.h"
#include "GmUiStructureCommandRegister.h"
#include "CmdStatusUtils.h"
#include "AddStructureDynamicPannelUtil.h"


#include "IModelView.h"
#include "GbmpModelViewTypes.h"
#include "UiCommonDialog.h"
#include "StructureDefaultFamilyNames.h"
#include "BuiltInStructureFamilies.h"
#include "IFamily.h"
#include "FamilyUtils.h"
#include "IFamilyLoadOptions.h"
#include "IFamilyType.h"
#include "IUserTransaction.h"
#include "ActionCreateStructureWallHole.h"
#include "StructureCmdParamIds.h"
#include "CommandParameters.h"
#include "StructureInstancePresetParameterUtils.h"
#include "IInstanceType.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace std;

REGISTER_GM_COMMAND(CmdDrawRectStructureWallHole)

CmdDrawRectStructureWallHole::CmdDrawRectStructureWallHole() :
    GbmpCommandBase(ID_CMD_DRAW_RECT_STRUCTURE_WALL_HOLE)
{
}

bool CmdDrawRectStructureWallHole::IsEnabled() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT;
}

bool CmdDrawRectStructureWallHole::IsVisible() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT;
}

bool CmdDrawRectStructureWallHole::OnExecuteCommand()
{
    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    const std::wstring& viewType = pModelView->GetUserDataId();

    if (PlanViewType != viewType && View3DViewType != viewType && ElevationViewType != viewType)
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"创建墙洞"), GBMP_TR(L"此视图下不支持创建墙洞"), (int)UiCommonDialog::ButtonType::OK);
        return false;
    }

    return true;
}

bool CmdDrawRectStructureWallHole::ResetCommand()
{
    return true;
}

void CmdDrawRectStructureWallHole::InitBuiltInFamily()
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    wstring familyName = STRUCTURE_RECT_WALL_HOLE_FAMILY_NAME;
    const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    if (!pFamily)
    {
        OwnerPtr<IUserTransaction> opUt = IUserTransaction::Create(pDoc, GBMP_TR(L"创建墙洞族"));

        BuiltInStructureFamilies::FamilyCreator familyCreator = BuiltInStructureFamilies::CreateBuiltInRectWallHoleFamilyDocument;
        DBG_WARN_AND_RETURN_VOID_UNLESS(familyCreator, L"无法创建对应的族文档创建器",L"GDMPLab",L"2024-03-30");

        std::wstring familyFilePath = familyCreator(familyName);
        DBG_WARN_AND_RETURN_VOID_UNLESS(!familyFilePath.empty(), L"无法创建对应的族文档",L"GDMPLab",L"2024-03-30");

        std::wstring errorMsg;
        pFamily = FamilyUtils::LoadFamily(pDoc, familyFilePath, errorMsg, nullptr);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamily, errorMsg,L"GDMPLab",L"2024-03-30");

        opUt->Commit();
    }
}

OwnerPtr<IAction> CmdDrawRectStructureWallHole::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    if (!OnExecuteCommand())
        return nullptr;

    ResetCommand();
    InitBuiltInFamily();

    // 获取新创建实例的族名称、实例类型
    std::wstring familyName;
    std::wstring familyType;
    {
        // 从命令参数读取
        auto itor = cmdParams.find(ID_CMD_PARAM_FAMILY_NAME);
        if (itor != cmdParams.end())
        {
            familyName = itor->second.AsWString();
        }
        itor = cmdParams.find(ID_CMD_PARAM_INSTANCE_TYPE);
        if (itor != cmdParams.end())
        {
            familyType = itor->second.AsWString();
        }
    }
    if (familyName.empty() || familyType.empty())
    {
        bool status = StructureInstancePresetParameterUtils::GetPresetFamilyNameAndInstanceType(pDoc, GetCategory(), GetCategorySecondKey(), familyName, familyType);
        if (!status)
        {
            familyName = STRUCTURE_RECT_WALL_HOLE_FAMILY_NAME;
        }
    }

    const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");

    if (familyType.empty())
    {
        const std::vector<const IFamilyType *> familyTypes = pFamily->GetFamilyTypes();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(familyTypes.size() > 0, L"至少要有一个族类型",L"GDMPLab",L"2024-03-30");
        familyType = familyTypes.at(0)->GetName();
    }

    const IInstanceType* pInstanceType = pFamily->GetInstanceTypeByName(familyType);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"invalid pInstanceType",L"GDMPLab",L"2024-03-30");

    OwnerPtr<ActionCreateStructureWallHole> opAction = NEW_AS_OWNER_PTR(ActionCreateStructureWallHole, GetCategory(), GetCategorySecondKey(), pFamily->GetElementId(), pInstanceType->GetElementId());
    return TransferOwnership(opAction);
}
